from rich import print
from typing import TYPE_CHECKING

from puzzle.board import Board
from puzzle.tile import Tile
from puzzle.component import Transform
from container import Tiles

from solver.SComponent import SComponent

from util.SConvert import make_scomponents

if TYPE_CHECKING:
    from io import TextIOWrapper, _WrappedBuffer

def _validate_board(board: Board) -> None:
    # Board shape
    assert board.row_length == (7, 9, 11, 11, 9, 7), "Mismatched board size"
    
    # Tiles
    all_tiles = Tiles.t_All.copy()
    all_tiles.remove(Tiles.blank)
    
    cnt_blank_tile = 0
    for row in board.tiles:
        for td in row:
            if td.tile == Tiles.blank:
                cnt_blank_tile += 1
                continue
            
            assert td.tile in all_tiles, f"Duplicated tile: {td.tile}"
            all_tiles.remove(td.tile)

    assert len(all_tiles) == 0, f"Missing tile: {", ".join(map(str, all_tiles))}"
    assert cnt_blank_tile == 4, f"Expect 4 blank tiles, got {cnt_blank_tile}"
    
def _validate_comps(comps: list[list[Transform]]) -> None:
    tot_size = 0
    for i in range(len(comps)):
        transforms = comps[i]
        
        comp_size = len(transforms[0].td)
        tot_size += comp_size
        
        for j in range(1, len(transforms)):
            assert len(transforms[j].td) == comp_size, f"Mismatched size: transform #{j+1} of component #{i+1}"
    
    assert tot_size == 47, f"Expect component size 47 in total, got {tot_size}"

def _load_board(fhand: "TextIOWrapper[_WrappedBuffer]", name: str, validation: bool = True) -> Board:
    tiles: list[list[Tile]] = [[] for _ in range(6)]
    for row in range(6):
        for label in fhand.readline().strip().split(" "):
            t = Tiles.label_tile_map.get(label)
            assert t is not None, f"Got invalid label {label} on row {row}"
            tiles[row].append(t)
    
    board = Board(name, tiles)
    if validation:
        _validate_board(board)
    return board
        
def load_from_file(name: str, filepath: str, validation: bool = True) -> tuple[Board, list[list[Transform]]]:
    fhand = open(filepath, "r", encoding="utf8")
    def _readline():
        return fhand.readline().strip()
        
    board = _load_board(fhand, name, validation)
        
    comps: list[list[Transform]] = []
    transforms: list[Transform] = []
    
    while True:
        line = _readline()
        if line == "":
            break
        
        if line.startswith("-"):
            if transforms:
                comps.append(transforms)
            transforms = []
        else:
            transforms.append(
                Transform.construct_from_label(board, line.split(" "))
            )
    
    if transforms:
        comps.append(transforms)
        
    if validation:
        _validate_comps(comps)
    
    return board, comps
